# 导入必要的包
import argparse # argparse解析命令行参数
import glob # 获取输入图像的路径
import cv2 # opencv绑定
import imutils # 图像处理的一些方法
import numpy as np # numpy进行数值处理

# 构建命令行及解析参数
# --template 模板路径
# --images 原始图像路径
# --visualize 标志是否显示每一个迭代的可视化结果
# ap = argparse.ArgumentParser()
# ap.add_argument("-t", "--template", required=True, help="Path to template image")
# ap.add_argument("-i", "--images", required=True,help="Path to images where template will be matched")
# ap.add_argument("-v", "--visualize",help="Flag indicating whether or not to visualize each iteration")
# args = vars(ap.parse_args())
def bianlifa():#遍历方法，备用代码
    # 加载模板图像，转换灰度图，检测边缘
    # 使用边缘而不是原始图像进行模板匹配可以大大提高模板匹配的精度。
    template = cv2.imread(args["template"])
    template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
    template = cv2.Canny(template, 50, 200)
    (tH, tW) = template.shape[:2]
    cv2.imshow("Template", template)

    # 遍历图像以匹配模板
    for imagePath in glob.glob(args["images"]+ "/*.jpg"):
        # 加载图像，转换为灰度图，初始化用于追踪匹配区域的簿记变量
        image = cv2.imread(imagePath)
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        found= None
        # 遍历图像尺寸
        for scale in np.linspace(0.2, 1.0, 20)[::-1]:
            # 根据scale比例缩放图像，并保持其宽高比
            resized= imutils.resize(gray, width=int(gray.shape[1]* scale))
            r= gray.shape[1]/ float(resized.shape[1])
            # 缩放到图像比模板小，则终止
            if resized.shape[0] < tH or resized.shape[1] < tW:
                break
            # 在缩放后的灰度图中检测边缘，进行模板匹配
            # 使用与模板图像完全相同的参数计算图像的Canny边缘表示；
            # 使用cv2.matchTemplate应用模板匹配；
            # cv2.minMaxLoc获取相关结果并返回一个4元组，其中分别包含最小相关值、最大相关值、最
            edged= cv2.Canny(resized, 50, 200)
            result= cv2.matchTemplate(edged, template, cv2.TM_CCOEFF)
            (_, maxVal, _, maxLoc)= cv2.minMaxLoc(result)
            # 检查是否可视化
            if args.get("visualize", False):
                # 在检测到的区域绘制边界框
                clone= np.dstack([edged, edged, edged])
                cv2.rectangle(clone, (maxLoc[0], maxLoc[1]),(maxLoc[0]+ tW, maxLoc[1]+ tH), (0,0, 255),2)
                cv2.imshow("Visualize", clone)
                cv2.waitKey(0)
            # 如果我们找到了一个新的最大校正值，更新簿记变量值
            if found is None or maxVal > found[0]:
                found= (maxVal, maxLoc, r)
        # 解包簿记变量并基于调整大小的比率，计算边界框（x，y）坐标
        (_, maxLoc, r) = found
        (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r))
        (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r))
        # 在检测结果上绘制边界框并展示图像
        cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2)
        cv2.imshow("Image", image)
        cv2.waitKey(0)
def locatee(source, wanted, accuracy=0.80):#自己加入的匹配低像素手机
    # 加载模板图像，转换灰度图，检测边缘
    # 使用边缘而不是原始图像进行模板匹配可以大大提高模板匹配的精度。
    template = cv2.imread(wanted)
    template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
    template = cv2.Canny(template, 50, 200)
    (tH, tW) = template.shape[:2]
    #cv2.imshow("Template", template)


    # 加载图像，转换为灰度图，初始化用于追踪匹配区域的簿记变量
    image = cv2.imread(source)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    found = None
    # 遍历图像尺寸
    for scale in np.linspace(1.0, 2.0, 20):#切片放大
        # 根据scale比例缩放图像，并保持其宽高比
        resized = imutils.resize(gray, width=int(gray.shape[1] * scale))#缩放
        r = gray.shape[1] / float(resized.shape[1])#保持纵横比
        # 缩放到图像比模板小，则终止
        # if resized.shape[0] < tH or resized.shape[1] < tW:
        #     break
        # 在缩放后的灰度图中检测边缘，进行模板匹配
        # 使用与模板图像完全相同的参数计算图像的Canny边缘表示；
        # 使用cv2.matchTemplate应用模板匹配；
        # cv2.minMaxLoc获取相关结果并返回一个4元组，其中分别包含最小相关值、最大相关值、最
        edged = cv2.Canny(resized, 50, 200)
        result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF)
        (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)
        # 检查是否可视化
        # if args.get("visualize", False):
        #     # 在检测到的区域绘制边界框
        #     clone = np.dstack([edged, edged, edged])
        #     cv2.rectangle(clone, (maxLoc[0], maxLoc[1]), (maxLoc[0] + tW, maxLoc[1] + tH), (0, 0, 255), 2)
        #     cv2.imshow("Visualize", clone)
        #     cv2.waitKey(0)
        # 如果我们找到了一个新的最大校正值，更新簿记变量值
        if found is None or maxVal > found[0]:
            found = (maxVal, maxLoc, r)
    # 解包簿记变量并基于调整大小的比率，计算边界框（x，y）坐标
    (_, maxLoc, r) = found
    (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r))
    (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r))
    # 在检测结果上绘制边界框并展示图像
    # cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2)
    #     # cv2.imshow("Image", image)
    #     # cv2.waitKey(0)
    #输出
    start = int(maxLoc[0] * r), int(maxLoc[1] * r)
    print(found)
    return start


# 从source图片中查找wanted图片所在的位置，当置信度大于accuracy时返回找到的最大置信度位置的左上角坐标
# 从source图片中查找wanted图片所在的位置，当置信度大于accuracy时返回找到的最大置信度位置的左上角坐标
def locate(source, wanted, accuracy=0.90):
    screen_cv2 = cv2.imread(source)
    wanted_cv2 = cv2.imread(wanted)
    # 获取模板的宽度和高度
    #w, h = wanted_cv2.shape[:-1]  # 对于灰度图或彩色图，获取宽度和高度
    h, w = wanted_cv2.shape[:-1]  # 对于灰度图或彩色图，获取宽度和高度

    result = cv2.matchTemplate(screen_cv2, wanted_cv2, cv2.TM_CCOEFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

    if max_val >= accuracy:
        left_top = max_loc
        # 计算模板右下角的坐标
        bottom_right = (max_loc[0] + w, max_loc[1] + h)
        zuobiaofanwei = (left_top, bottom_right)
        print("template宽高为", w, h)
        print(max_loc, bottom_right,max_val)
        return (left_top, bottom_right)
    else:
        print(max_loc, max_val)
        return None

def fengezuobiao():#分割左上右下坐标实例代码，备用
    points = ((1, 2), (3, 4))

    # 获取第一个点的坐标
    point1_x, point1_y = points[0]
    print("Point 1:", point1_x, point1_y)

    # 获取第二个点的坐标
    point2_x, point2_y = points[1]
    print("Point 2:", point2_x, point2_y)

# 从source图片中查找wanted图片所在的位置，当置信度大于accuracy时返回找到的所有位置的左上角坐标（自动去重）
def locate_all(source, wanted, accuracy=0.90):
    """
    从source图片中查找wanted图片所在的位置，当置信度大于accuracy时返回找到的所有位置的左上角坐标（自动去重）


    """
    loc_pos = []
    screen_cv2 = cv2.imread(source)
    wanted_cv2 = cv2.imread(wanted)
    # 将模板图片转换为灰度图
    template_gray = cv2.cvtColor(wanted_cv2, cv2.COLOR_BGR2GRAY)


    # 将主图转换为灰度图
    main_image_gray = cv2.cvtColor(screen_cv2, cv2.COLOR_BGR2GRAY)
    beijing_img = cv2.GaussianBlur(main_image_gray, (5, 5), 0)
    result = cv2.matchTemplate(beijing_img, template_gray, cv2.TM_CCOEFF_NORMED)
    location = np.where(result >= accuracy)

    ex, ey = 0, 0
    for pt in zip(*location[::-1]):
        x = pt[0]
        y = pt[1]

        if (x - ex) + (y - ey) < 15:  # 去掉邻近重复的点
            continue
        ex, ey = x, y

        loc_pos.append([int(x), int(y)])


    return loc_pos

# 给定目标尺寸大小和目标左上角顶点坐标，即可给出目标中心的坐标
def centerOfTouchArea(wantedSize, topLeftPos):
    tlx, tly = topLeftPos
    h_src, w_src, tongdao = wantedSize
    if tlx < 0 or tly < 0 or w_src <=0 or h_src <= 0:
        return None
    return (tlx + w_src/2, tly + h_src/2)

